﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.AddIn.Pipeline;
using System.Windows;

namespace RootfusAddinView
{
    /// <summary>
    /// Base class for add-in items that will be placed on the Rootfus surface.
    /// </summary>
    [AddInBase]
    public abstract class RootfusSurfaceItem
    {
        /// Return the WPF UIElement for this addin that is displayed when settings aren't selected.
        abstract public FrameworkElement SurfaceUI
        {
            get;
        }

        /// <summary>
        /// Return the UI element for configuration settings.
        /// </summary>
        abstract public FrameworkElement ConfigUI
        {
            get;
        }

        /// <summary>
        /// Called when the UI for the config dialog box is done being shown.
        /// Default implementation does nothing.
        /// </summary>
        virtual public void ConfigDone()
        {
        }

        /// <summary>
        /// Return true if you have a settings UI element - so we don't have to
        /// ask extra memory just to know...
        /// </summary>
        abstract public bool HasSettingsUI
        {
            get;
        }

        /// <summary>
        /// Returns true if the user is allowed to resize the item.
        /// </summary>
        virtual public bool SurfaceUIResizeAllowed
        {
            get { return false; }
        }

        /// <summary>
        /// Request a new size. We have a default implementation here -- which should
        /// work for most things. But should not be called unless the subclass overrides
        /// the above SurfaceUIResizeAllowed...
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        virtual public void RequestResize(double width, double height)
        {
            SurfaceUI.Height = height;
            SurfaceUI.Width = width;
        }

        /// Returns a list of the input and output pins
        abstract public IList<PinDefinition> InputPins
        {
            get;
        }

        /// <summary>
        /// Returns the list of output pins. The names of these pins must be
        /// unique!!
        /// </summary>
        abstract public IList<string> OutputPinNames
        {
            get;
        }

        /// <summary>
        /// Called when the add-in should update itself because, perhaps, one of
        /// its inputs has changed.
        /// </summary>
        abstract public void Update();

        /// Help keep track of the updater object for our subclasses.
        private SICallback _callback;

        /// <summary>
        /// Called to set the callback.
        /// </summary>
        /// <param name="callback"></param>
        virtual public void SetCallback(SICallback callback)
        {
            _callback = callback;
        }

        /// <summary>
        /// Get the callback object to contact the rootfus app with changes to state, etc.
        /// </summary>
        public SICallback Callback
        {
            get { return _callback; }
        }

        /// <summary>
        /// Return the pin data as a root object. Override it if you do something like this!
        /// </summary>
        /// <param name="pin"></param>
        /// <returns></returns>
        virtual public ROOTObjectSpec GetPinDataAsROOTObject(string pinname)
        {
            ROOTNET.Interface.NTObject obj = GetPinDataAsTObject(pinname);
            if (obj == null)
            {
                return null;
            }

            ///
            /// Now, convert it into the proper guy!
            /// 

            ROOTObjectSpec spec = new ROOTObjectSpec();
            spec._native_pointer = obj.GetRawCPPPointer();
            return spec;
        }

        /// <summary>
        /// Return a TObject for root data. Hides some of the mess you'd have to go through otherwise!
        /// </summary>
        /// <param name="pin"></param>
        /// <returns></returns>
        virtual public ROOTNET.Interface.NTObject GetPinDataAsTObject(string pin)
        {
            return null;
        }
        /// <summary>
        /// Called when the config xml is changing. Update yourself! Default ignores the call.
        /// </summary>
        /// <param name="xml_config"></param>
        virtual public void SetConfigXML(string xml_config)
        {
        }
    }
}
